home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / binsim.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  13KB  |  559 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * The routines in this file handle binary network files input/output.
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include "defs.h"
  21. #include "net.h"
  22. #include "globals.h"
  23. #include "bin_io.h"
  24. #include "net_macros.h"
  25.  
  26.  
  27. private    FILE    *fnet;            /* file for reading/writing network */
  28. private    tptr    rd_tlist;        /* list of transistor just read */
  29. private    double    inet_CTGA;        /* transistor capacitances */
  30. private    double    inet_CTDE;
  31. private    double    inet_CTDW;
  32. private    long    inet_lambda;
  33. private    void    adjust_transistors();
  34.  
  35. private    char    netHeader[] = "<<inet>>";
  36. private    char    endAscii[] = "<end>\n";
  37.  
  38. #define    CM_M    100.0            /* centimicrons per micron */
  39. #define    CM_M2    ( CM_M * CM_M )        /* centimicrons per micron ^ 2 */
  40.  
  41.  
  42. #define    HEADER_LEN        (sizeof( netHeader ) - 1)
  43.  
  44.     /* define number of bytes used to write/read network parameter */
  45. #define    NB_NDINDEX    4
  46. #define    NB_NCAP        4
  47. #define    NB_TSIZE    4
  48. #define    NB_COORD    4
  49. #define    NB_VTHRESH    2
  50. #define    NB_TP        2
  51. #define    NB_STRLEN    2
  52. #define    NB_FLAGS    1
  53. #define    NB_TTYPE    1
  54.  
  55.     /* node flags we are interested in preserving */
  56. #define    SAVE_FLAGS    (POWER_RAIL | ALIAS | USERDELAY)
  57.  
  58.     /* scale factors for floating-point numbers */
  59. #define    VTH_SCALE        1000.0
  60. #define    CAP_SCALE        16384.0    /* power of 2 to minimize error */
  61.  
  62.  
  63. typedef struct        /* format of node records in net file */
  64.   {
  65.     union
  66.       {
  67.     char  cap[ NB_NCAP ];
  68.     char  alias[ NB_NDINDEX ];
  69.       } n;
  70.     char  flags[ NB_FLAGS ];
  71.     char  slen[ NB_STRLEN ];
  72.   } File_Node;
  73.  
  74. #define    Size_File_Node        ( NB_NDINDEX + NB_FLAGS + NB_STRLEN )
  75.  
  76.  
  77. typedef struct        /* format of node user-delays in net file */
  78.   {
  79.     char  tphl[ NB_TP ];
  80.     char  tplh[ NB_TP ];
  81.   } File_Delay;
  82.  
  83. #define    Size_File_Delay        ( NB_TP + NB_TP )
  84.  
  85.  
  86. typedef struct        /* format of node thresholds in net file */
  87.   {
  88.     char  vhigh[ NB_VTHRESH ];
  89.     char  vlow[ NB_VTHRESH ];
  90.   } File_Thresh;
  91.  
  92. #define    Size_File_Thresh     ( NB_VTHRESH + NB_VTHRESH )
  93.  
  94.  
  95. typedef struct        /* format of transistor records in net file */
  96.   {
  97.     char  width[ NB_TSIZE ];
  98.     char  length[ NB_TSIZE ];
  99.     char  ttype[ NB_TTYPE ];
  100.     char  gate[ NB_NDINDEX ];
  101.     char  src[ NB_NDINDEX ];
  102.     char  drn[ NB_NDINDEX ];
  103.     char  x[ NB_COORD ];
  104.     char  y[ NB_COORD ];
  105.   } File_Trans;
  106.  
  107. #define    Size_File_Trans    ( NB_TSIZE + NB_TSIZE + NB_TTYPE + \
  108.         NB_NDINDEX + NB_NDINDEX + NB_NDINDEX + NB_COORD + NB_COORD )
  109.  
  110.  
  111. private tptr wr_nodes()
  112.   {
  113.     register nptr  n;
  114.     register tptr  txlist;
  115.     register lptr  l;
  116.     File_Node      node;
  117.     File_Delay     delays;
  118.     File_Thresh    thresh;
  119.     int            slen;
  120.     double         cap;
  121.     float          vhigh = HIGHTHRESH, vlow = LOWTHRESH;
  122.  
  123.     txlist = NULL;
  124.  
  125.     for( n = GetNodeList(); n != NULL; n = n->n.next )
  126.       {
  127.     cap = n->ncap;
  128.     for( l = n->nterm; l != NULL; l = l->next )
  129.       {
  130.         register tptr  t = l->xtor;
  131.  
  132.         if( not (t->tflags & ACTIVE_T) )
  133.           {
  134.         t->scache.t = txlist;
  135.         txlist = t;
  136.         t->tflags |= ACTIVE_T;
  137.           }
  138.         if( t->ttype & GATELIST )
  139.           cap += (StackCap( t ) / 2.0);
  140.       }
  141.     
  142.     slen = strlen( pnode( n ) ) + 1;
  143.     PackBytes( node.slen, slen, NB_STRLEN );
  144.     node.flags[0] = n->nflags & SAVE_FLAGS;
  145.     if( n->vhigh != vhigh or n->vlow != vlow )
  146.         node.flags[0] |= WATCHED;
  147.     if( n->nflags & ALIAS )
  148.         PackBytes( node.n.alias, Node2index( n->nlink ), NB_NDINDEX )
  149.     else
  150.         PackBytes( node.n.cap, cap * CAP_SCALE, NB_NCAP );
  151.     (void) Fwrite( &node, Size_File_Node, fnet );
  152.     (void) Fwrite( pnode( n ), slen, fnet );
  153.  
  154.     if( n->nflags & USERDELAY )
  155.       {
  156.         PackBytes( delays.tphl, n->tphl, NB_TP );
  157.         PackBytes( delays.tplh, n->tplh, NB_TP );
  158.         (void) Fwrite( &delays, Size_File_Delay, fnet );
  159.       }
  160.     if( node.flags[0] & WATCHED )
  161.       {
  162.         PackBytes( thresh.vhigh, n->vhigh * VTH_SCALE, NB_VTHRESH );
  163.         PackBytes( thresh.vlow, n->vlow * VTH_SCALE, NB_VTHRESH );
  164.         (void) Fwrite( &thresh, Size_File_Thresh, fnet );
  165.       }
  166.       }
  167.  
  168.     return( txlist );
  169.   }
  170.  
  171.  
  172. private void wr_trans( t )
  173.   register tptr  t;
  174.   {
  175.     File_Trans  trans;
  176.     Ulong       ndindx;
  177.  
  178.     if( t->ttype & ORED )
  179.       {
  180.     for( t = t->tlink; t != NULL; t = t->scache.t ) wr_trans( t );
  181.     return;
  182.       }
  183.  
  184.     ndindx = Node2index( t->gate );
  185.     PackBytes( trans.gate, ndindx, NB_NDINDEX );
  186.  
  187.     ndindx = Node2index( t->source );
  188.     PackBytes( trans.src, ndindx, NB_NDINDEX );
  189.  
  190.     ndindx = Node2index( t->drain );
  191.     PackBytes( trans.drn, ndindx, NB_NDINDEX );
  192.  
  193.     PackBytes( trans.length, t->r->length, NB_TSIZE );
  194.     PackBytes( trans.width, t->r->width, NB_TSIZE );
  195.  
  196.     trans.ttype[0] = t->ttype & ~(ORED | ORLIST | STACKED | GATELIST);
  197.  
  198.     if( t->tlink != t )
  199.       {
  200.     trans.ttype[0] |= GATELIST;
  201.     PackBytes( trans.x, t->x.pos, NB_COORD );
  202.     PackBytes( trans.y, t->y.pos, NB_COORD );
  203.       }
  204.  
  205.     (void) Fwrite( &trans, Size_File_Trans, fnet );
  206.   }
  207.  
  208.  
  209. private void wr_txtors( tlist )
  210.   tptr  tlist;
  211.   {
  212.     register tptr  t, next;
  213.  
  214.     for( t = tlist; t != NULL; t = next )
  215.       {
  216.     next = t->scache.t;
  217.  
  218.     t->tflags &= ~ACTIVE_T;
  219.     t->scache.t = NULL;
  220.  
  221.     if( t->ttype & GATELIST )
  222.       {
  223.         for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  224.         wr_trans( t );
  225.       }
  226.     else
  227.         wr_trans( t );
  228.       }
  229.  
  230.     for( t = tcap->dcache.t; t != tcap; t = t->dcache.t )
  231.     wr_trans( t );
  232.   }
  233.  
  234.  
  235. private void WriteAscii( f )
  236.   FILE  *f;
  237.   {
  238.     (void) fprintf( f, "lambda %ld\n", LAMBDACM );
  239.     (void) fprintf( f, "CTGA %.6f\n", CTGA * CM_M2 );
  240.     (void) fprintf( f, "CTDW %.6f\n", CTDW * CM_M );
  241.     (void) fprintf( f, "CTDE %.6f\n", CTDE );
  242.  
  243.     /* add extensions here */
  244.     (void) fprintf( f, endAscii );
  245.   }
  246.  
  247.  
  248. private int ReadAscii( f, line )
  249.   FILE  *f;
  250.   char  *line;
  251.   {
  252.     int  nl = 0;
  253.  
  254.     inet_CTGA = CTGA;
  255.     inet_CTDE = CTDE;
  256.     inet_CTDW = CTDW;
  257.     inet_lambda = LAMBDACM;
  258.  
  259.     do
  260.       {
  261.     if( fgetline( line, 200, f ) == NULL )
  262.         return( -1 );
  263.     nl++;
  264.     if( strcmp( line, endAscii ) == 0 )
  265.         return( 0 );
  266.     if( strncmp( line, "lambda ", 7 ) == 0 )
  267.         inet_lambda = atoi( line + 7 );
  268.     if( strncmp( line, "CTGA ", 5 ) == 0 )
  269.         inet_CTGA = atof( line + 5 ) / CM_M2;
  270.     else if( strncmp( line, "CTDW ", 5 ) == 0 )
  271.         inet_CTDW = atof( line + 5 ) / CM_M;
  272.     else if( strncmp( line, "CTDE ", 5 ) == 0 )
  273.         inet_CTDE = atof( line + 5 );
  274.  
  275.     /* add extensions here */
  276.       }
  277.     while( nl < 30 );
  278.  
  279.     (void) fprintf( stderr, "inet file seems bad\n" );
  280.     return( -1 );
  281.   }
  282.  
  283.  
  284. public void wr_netfile( fname )
  285.   char  *fname;
  286.   {
  287.     tptr  txlist;
  288.  
  289.     if( (fnet = fopen( fname, "w" )) == NULL )
  290.       {
  291.     (void) fprintf( stderr, "can't open file '%s'\n", fname );
  292.     return;
  293.       }
  294.  
  295.     (void) fprintf( fnet, "%s\n", netHeader );
  296.     (void) fprintf( fnet, "%d %d\n", GetHashSize(), nnodes + naliases );
  297.  
  298.     WriteAscii( fnet );
  299.     txlist = wr_nodes();
  300.     wr_txtors( txlist );
  301.     (void) fclose( fnet );
  302.   }
  303.  
  304.  
  305. private void PrematureEof()
  306.   {
  307.     (void) fprintf( stderr, "premature eof in inet file\n" );
  308.     exit( 1 );
  309.   }
  310.  
  311.  
  312. private void rd_nodes( nname, n_nodes )
  313.   char  *nname;
  314.   int   n_nodes;
  315.   {
  316.     File_Node    node;
  317.     File_Delay   delays;
  318.     File_Thresh  thresh;
  319.     Ulong        tmp;
  320.     int          slen;
  321.     nptr         n;
  322.     nptr         aliases;
  323.  
  324.     aliases = NULL;
  325.     while( n_nodes-- != 0 )
  326.       {
  327.     if( Fread( &node, Size_File_Node, fnet ) != Size_File_Node )
  328.         PrematureEof();
  329.  
  330.     UnpackBytes( node.slen, slen, NB_STRLEN );
  331.     if( Fread( nname, slen, fnet ) != slen )
  332.         PrematureEof();
  333.  
  334.     n = GetNode( nname );
  335.  
  336.     n->nflags = node.flags[0];
  337.     if( n->nflags & ALIAS )
  338.       {
  339.         UnpackBytes( node.n.alias, tmp, NB_NDINDEX );
  340.         n->c.time = tmp;
  341.  
  342.         n->n.next = aliases;
  343.         aliases = n;
  344.       }
  345.     else
  346.       {
  347.         UnpackBytes( node.n.cap, tmp, NB_NCAP );
  348.         n->ncap = tmp * (1/CAP_SCALE);
  349.         if( n->ncap < MIN_CAP )
  350.         n->ncap = MIN_CAP;
  351.       }
  352.  
  353.     if( n->nflags & USERDELAY )
  354.       {
  355.         if( Fread( &delays, Size_File_Delay, fnet ) != Size_File_Delay )
  356.         PrematureEof();
  357.         UnpackBytes( delays.tphl, n->tphl, NB_TP );
  358.         UnpackBytes( delays.tplh, n->tplh, NB_TP );
  359.       }
  360.     if( n->nflags & WATCHED )
  361.       {
  362.         n->nflags &= ~WATCHED;
  363.         if( Fread( &thresh, Size_File_Thresh, fnet ) != Size_File_Thresh )
  364.         PrematureEof();
  365.         UnpackBytes( thresh.vhigh, tmp, NB_VTHRESH );
  366.         n->vhigh = tmp * (1/VTH_SCALE);
  367.         UnpackBytes( thresh.vlow, tmp, NB_VTHRESH );
  368.         n->vlow = tmp * (1/VTH_SCALE);
  369.       }
  370.       }
  371.  
  372.     VDD_node->nflags |= INPUT;        /* these bits get thrashed above */
  373.     GND_node->nflags |= INPUT;
  374.  
  375.     for( n = aliases; n != NULL; n = n->n.next )
  376.       {
  377.     n->nlink = Index2node( n->c.time );
  378.     n->c.time = 0;
  379.     nnodes--;
  380.     naliases++;
  381.       }
  382.   }
  383.  
  384.  
  385. private void rd_txtors()
  386.   {
  387.     File_Trans  trans;
  388.     Ulong       ndindx;
  389.     long        width, length;
  390.     tptr        t, *last;
  391.  
  392.     rd_tlist = NULL;
  393.     last = &rd_tlist;
  394.     while( Fread( &trans, Size_File_Trans, fnet ) == Size_File_Trans )
  395.       {
  396.     NEW_TRANS( t );
  397.  
  398.     UnpackBytes( trans.gate, ndindx, NB_NDINDEX );
  399.     t->gate = Index2node( ndindx );
  400.  
  401.     UnpackBytes( trans.src, ndindx, NB_NDINDEX );
  402.     t->source = Index2node( ndindx );
  403.  
  404.     UnpackBytes( trans.drn, ndindx, NB_NDINDEX );
  405.     t->drain = Index2node( ndindx );
  406.  
  407.     UnpackBytes( trans.width, width, NB_TSIZE );
  408.     UnpackBytes( trans.length, length, NB_TSIZE );
  409.  
  410.     t->ttype = trans.ttype[0];
  411.  
  412.     if( t->ttype & GATELIST )
  413.       {
  414.         t->ttype &= ~GATELIST;
  415.         UnpackBytes( trans.x, t->x.pos, NB_COORD );
  416.         UnpackBytes( trans.y, t->y.pos, NB_COORD );
  417.         EnterPos( t, TRUE );
  418.       }
  419.     else
  420.         EnterPos( t, FALSE );
  421.  
  422.     t->r = requiv( (int) t->ttype, width, length );
  423.  
  424.     ntrans[ BASETYPE( t->ttype ) ] += 1;
  425.  
  426.     *last = t;
  427.     last = &(t->scache.t);
  428.       }
  429.     *last = NULL;
  430.   }
  431.  
  432.  
  433. public int rd_netfile( f, line )
  434.   FILE  *f;
  435.   char  *line;
  436.   {
  437.     int   hash_size, n_nodes;
  438.     char  *s;
  439.  
  440.     if( strncmp( line, netHeader, HEADER_LEN ) != 0 )
  441.     return( FALSE );
  442.  
  443.     if( fgetline( line, 200, f ) == NULL )
  444.     PrematureEof();
  445.  
  446.     if( sscanf( line, "%d %d", &hash_size, &n_nodes ) != 2 )
  447.       {
  448.     (void) fprintf( stderr, "bad format for net file\n" );
  449.     exit( 1 );
  450.       }
  451.  
  452.     if( hash_size != GetHashSize() )
  453.       {
  454.     (void) fprintf( stderr, "Incompatible net file version\n" );
  455.     exit( 1 );
  456.       }
  457.  
  458.     if( ReadAscii( f, line ) ) PrematureEof();
  459.  
  460.     fnet = f;
  461.     rd_nodes( line, n_nodes );
  462.     rd_txtors();
  463.  
  464.     adjust_transistors( rd_tlist );
  465.  
  466.     return( TRUE );
  467.   }
  468.  
  469.  
  470. private void adjust_transistors( tlist )
  471.   tptr  tlist;
  472.   {
  473.     double         adj_g, adj_w, adj_e;
  474.     register tptr  t;
  475.  
  476. #    define    ABS( X )    ( ((X) < 0) ? -(X) : (X) )
  477. #    ifndef CAP_ADJUST_LIMIT
  478. #    define    CAP_ADJUST_LIMIT    0.0000005
  479. #    endif
  480. #    define    G_CAP_ADJUST_LIMIT    (CAP_ADJUST_LIMIT / CM_M2)
  481. #    define    W_CAP_ADJUST_LIMIT    (CAP_ADJUST_LIMIT / CM_M)
  482.  
  483.     adj_g = CTGA - inet_CTGA;
  484.     adj_w = CTDW - inet_CTDW;
  485.     adj_e = CTDE - inet_CTDE;
  486.  
  487.     if( LAMBDACM != inet_lambda and LAMBDACM > 0 and inet_lambda > 0 )
  488.       {
  489.     double  adj_size = (double) LAMBDACM / (double) inet_lambda;
  490.  
  491.     for( t = tlist; t != NULL; t = t->scache.t )
  492.       {
  493.         t->r->length *= adj_size;    t->r->width *= adj_size;
  494.       }
  495.       }
  496.  
  497.     if( ABS( adj_g ) > G_CAP_ADJUST_LIMIT )
  498.       {
  499.     for( t = tlist; t != NULL; t = t->scache.t )
  500.         t->gate->ncap += adj_g * t->r->length * t->r->width;
  501.       }
  502.  
  503.     if( ABS( adj_w ) > W_CAP_ADJUST_LIMIT or ABS( adj_e ) > CAP_ADJUST_LIMIT )
  504.       {
  505.     for( t = tlist; t != NULL; t = t->scache.t )
  506.       {
  507.         t->source->ncap += adj_w * t->r->width + adj_e;
  508.         t->drain->ncap += adj_w * t->r->width + adj_e;
  509.       }
  510.       }
  511.   }
  512.  
  513.  
  514. /*
  515.  * Traverse the transistor list and add the node connection-list.  We have
  516.  * to be careful with ALIASed nodes.  Note that transistors with source/drain
  517.  * connected to VDD and GND nodes are not linked.
  518.  */
  519. public nptr bin_connect_txtors()
  520.   {
  521.     register tptr  t, tnext;
  522.     register nptr  nd_list = NULL;
  523.  
  524.     for( t = rd_tlist; t != NULL; t = tnext )
  525.       {
  526.     tnext = t->scache.t;
  527.     t->state = ( t->ttype & ALWAYSON ) ? WEAK : UNKNOWN;
  528.     t->tflags = 0;
  529.  
  530.     if( t->ttype & TCAP )
  531.       {
  532.         LINK_TCAP( t );
  533.       }
  534.     else
  535.       {
  536.         if( t->ttype & ALWAYSON )
  537.           {
  538.         CONNECT( on_trans, t );
  539.           }
  540.         else
  541.           {
  542.         CONNECT( t->gate->ngate, t );
  543.           }
  544.  
  545.         if( not (t->source->nflags & POWER_RAIL) )
  546.           {
  547.         CONNECT( t->source->nterm, t );
  548.         LINK_TO_LIST( t->source, nd_list, VISITED );
  549.           }
  550.         if( not (t->drain->nflags & POWER_RAIL) )
  551.           {
  552.         CONNECT( t->drain->nterm, t );
  553.         LINK_TO_LIST( t->drain, nd_list, VISITED );
  554.           }
  555.       }
  556.       }
  557.     return( nd_list );
  558.   }
  559.